package org.supda.system.aop;

import java.lang.reflect.Method;
import java.sql.Timestamp;

import javax.inject.Inject;

import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.supda.system.annoation.SysLog;
import org.supda.system.entity.TLog;
import org.supda.system.entity.TUser;
import org.supda.system.service.TLogService;

/**
 * 
 * @author supda
 * @Date 2017-3-13 下午4:19:12
 * 
 *       AOP日志处理
 */
@Aspect
@Component
public class TlogAopHandler {

	Logger logger = Logger.getLogger(TlogAopHandler.class);
	
	@Inject
	private TLogService tLogService;

	// Controller层切点
/*	@Pointcut("execution (* org.supda.system.controller..*.*(..))")
	public void controllerAspect() {
	}*/
	
	//Controller层切点    
    @Pointcut("@annotation(org.supda.system.annoation.SysLog)")    
     public  void controllerAspect() {    
    }  

	//环绕通知
    @Around("controllerAspect()")
	public Object around(JoinPoint joinPoint) throws Throwable {
    	TLog tLog = null;
		Object result = null;
    	//System.out.println("==========开始执行controller环绕通知===============");
		long start = System.currentTimeMillis();
		try {
			
			 //前置通知
			result = ((ProceedingJoinPoint) joinPoint).proceed();
			
			long end = System.currentTimeMillis();
			
			tLog = process(joinPoint, end, start);
		
			//后置通知

			//System.out.println("==========结束执行controller环绕通知===============");
		} catch (Throwable e) {
			//异常通知
			logger.info("执行异常，日志记录失败！"+e);

			//不对异常进行处理，异常抛出，交给BaseController统一处理
			throw e;
		}finally{
			
			//记录日志
			if(tLog!=null){
				tLogService.create(tLog);
			}
			
		}
		return result;
	}
	
	
	//生成日志信息
	private TLog process(JoinPoint joinPoint, Long end, Long start) throws RuntimeException{
		
		Session session = SecurityUtils.getSubject().getSession();
		
		TUser user = (TUser)session.getAttribute("userSession");
		
		 try {  
	            String targetName = joinPoint.getTarget().getClass().getName();  
	            String methodName = joinPoint.getSignature().getName();  
	            Object[] arguments = joinPoint.getArgs();  
	            Class targetClass = Class.forName(targetName);  
	            Method[] methods = targetClass.getMethods();
	            String module = "";
	            String methodStr = "";
	            String desc = "";
	             for (Method method : methods) {  
	                 if (method.getName().equals(methodName)) {  
	                    Class[] clazzs = method.getParameterTypes();  
	                     if (clazzs.length == arguments.length) {  
	                    	 module = method.getAnnotation(SysLog.class).module();
	                    	 methodStr = method.getAnnotation(SysLog.class).method();
	                         desc = method.getAnnotation(SysLog.class).desc();
	                         break;  
	                    }  
	                }  
	            }         
	            
	            //*========数据库日志=========*//  
	            TLog tlog = new TLog(
	            		user.getAccountName(),
	            		module,
	            		methodStr,
	            		(end-start)+"",
	            		session.getHost(),
	            		new Timestamp(System.currentTimeMillis()),
	            		desc);
	            
	            //保存数据库  
	            return tlog;
	            
	        }  catch (Exception e) {  
	            //记录本地异常日志  
	            logger.error("==后置通知异常=="+e);  
	            return null;
	        }  
	}

}
